"""
权限API模块

提供权限管理相关的所有API接口，包括：
- 权限的增删改查
- 权限资源管理
- 角色权限关联
- 权限验证
"""
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from datetime import datetime, timezone
from typing import Optional, List
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from db.models import Permission, Role, RolePermission, User
from db.session import get_db
from apis.user_api import get_current_user
from services.permission import require_permission, PermissionCodes

router = APIRouter(prefix="/permissions", tags=["权限管理"])

security = HTTPBearer()

class PermissionCreate(BaseModel):
    """权限创建请求模型"""
    name: str
    code: str
    resource: str
    action: str
    description: Optional[str] = None

class PermissionUpdate(BaseModel):
    """权限更新请求模型"""
    name: Optional[str] = None
    code: Optional[str] = None
    resource: Optional[str] = None
    action: Optional[str] = None
    description: Optional[str] = None

class PermissionResponse(BaseModel):
    """权限响应模型"""
    id: int
    name: str
    code: str
    resource: str
    action: str
    description: Optional[str]
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True

class PermissionListResponse(BaseModel):
    permissions: List[PermissionResponse]
    total: int
    page: int
    pageSize: int

@router.post("/", response_model=PermissionResponse, summary="创建权限")
@require_permission(PermissionCodes.PERMISSION_CREATE)
async def create_permission(
    permission: PermissionCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    创建新权限
    
    Args:
        permission: 权限创建数据
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        PermissionResponse: 创建的权限信息
        
    Raises:
        HTTPException: 权限代码已存在或权限不足时抛出异常
    """
    # 检查权限代码是否已存在
    result = await db.execute(select(Permission).where(Permission.code == permission.code))
    if result.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="权限代码已存在"
        )
    
    # 创建权限
    db_permission = Permission(
        name=permission.name,
        code=permission.code,
        resource=permission.resource,
        action=permission.action,
        description=permission.description
    )
    
    db.add(db_permission)
    await db.commit()
    await db.refresh(db_permission)
    
    return db_permission

@router.get("/", response_model=PermissionListResponse, summary="获取权限列表")
@require_permission(PermissionCodes.PERMISSION_READ)
async def get_all_permissions(
    page: int = 1,
    pageSize: int = 10,
    search: str = "",
    resource: str = "",
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    获取权限列表（分页）
    
    Args:
        page: 页码
        pageSize: 每页数量
        search: 搜索关键词
        resource: 资源筛选
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        PermissionListResponse: 权限列表和分页信息
        
    Raises:
        HTTPException: 权限不足时抛出异常
    """
    # 构建查询
    query = select(Permission)
    
    # 添加搜索条件
    if search:
        query = query.where(
            Permission.name.contains(search) | 
            Permission.code.contains(search) |
            Permission.resource.contains(search)
        )
    
    # 添加资源筛选
    if resource:
        query = query.where(Permission.resource == resource)
    
    # 获取总数
    count_query = select(func.count(Permission.id))
    if search:
        count_query = count_query.where(
            Permission.name.contains(search) | 
            Permission.code.contains(search) |
            Permission.resource.contains(search)
        )
    if resource:
        count_query = count_query.where(Permission.resource == resource)
    
    total_result = await db.execute(count_query)
    total = total_result.scalar() or 0
    
    # 添加分页
    query = query.offset((page - 1) * pageSize).limit(pageSize)
    
    # 执行查询
    result = await db.execute(query)
    permissions = result.scalars().all()
    
    return PermissionListResponse(
        permissions=[PermissionResponse(
            id=permission.id,
            name=permission.name,
            code=permission.code,
            resource=permission.resource,
            action=permission.action,
            description=permission.description,
            created_at=permission.create_time,
            updated_at=permission.update_time
        ) for permission in permissions],
        total=total,
        page=page,
        pageSize=pageSize
    )

@router.get("/{permission_id}", response_model=PermissionResponse, summary="获取权限详情")
@require_permission(PermissionCodes.PERMISSION_READ)
async def get_permission(
    permission_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    获取权限详情
    
    Args:
        permission_id: 权限ID
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        PermissionResponse: 权限详细信息
        
    Raises:
        HTTPException: 权限不存在或权限不足时抛出异常
    """
    result = await db.execute(select(Permission).where(Permission.id == permission_id))
    permission = result.scalar_one_or_none()
    
    if not permission:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="权限不存在"
        )
    
    return permission

@router.put("/{permission_id}", response_model=PermissionResponse, summary="更新权限")
@require_permission(PermissionCodes.PERMISSION_UPDATE)
async def update_permission(
    permission_id: int,
    permission_update: PermissionUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    更新权限信息
    
    Args:
        permission_id: 权限ID
        permission_update: 权限更新数据
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        PermissionResponse: 更新后的权限信息
        
    Raises:
        HTTPException: 权限不存在或权限不足时抛出异常
    """
    # 查找权限
    result = await db.execute(select(Permission).where(Permission.id == permission_id))
    permission = result.scalar_one_or_none()
    
    if not permission:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="权限不存在"
        )
    
    # 更新权限信息
    if permission_update.name is not None:
        permission.name = permission_update.name
    
    if permission_update.code is not None:
        # 检查权限代码是否已被使用
        existing_permission = await db.execute(select(Permission).where(
            Permission.code == permission_update.code,
            Permission.id != permission_id
        ))
        if existing_permission.scalar_one_or_none():
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="权限代码已存在"
            )
        permission.code = permission_update.code
    
    if permission_update.resource is not None:
        permission.resource = permission_update.resource
    
    if permission_update.action is not None:
        permission.action = permission_update.action
    
    if permission_update.description is not None:
        permission.description = permission_update.description
    
    # 更新时间
    permission.update_time = datetime.now(timezone.utc)
    
    await db.commit()
    await db.refresh(permission)
    
    return permission

@router.delete("/{permission_id}", summary="删除权限")
@require_permission(PermissionCodes.PERMISSION_DELETE)
async def delete_permission(
    permission_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    删除权限
    
    Args:
        permission_id: 权限ID
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        dict: 删除结果
        
    Raises:
        HTTPException: 权限不存在、有角色使用或权限不足时抛出异常
    """
    # 查找权限
    result = await db.execute(select(Permission).where(Permission.id == permission_id))
    permission = result.scalar_one_or_none()
    
    if not permission:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="权限不存在"
        )
    
    # 检查是否有角色使用此权限
    role_permission_result = await db.execute(select(RolePermission).where(RolePermission.permission_id == permission_id))
    if role_permission_result.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="该权限下有角色，无法删除"
        )
    
    await db.delete(permission)
    await db.commit()
    
    return {"message": "权限删除成功"}

@router.get("/{permission_id}/roles", summary="获取权限角色")
@require_permission(PermissionCodes.PERMISSION_READ)
async def get_permission_roles(
    permission_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    获取使用该权限的角色列表
    
    Args:
        permission_id: 权限ID
        current_user: 当前用户对象
        db: 数据库会话
        
    Returns:
        dict: 角色列表
        
    Raises:
        HTTPException: 权限不存在或权限不足时抛出异常
    """
    # 查找权限
    result = await db.execute(select(Permission).where(Permission.id == permission_id))
    permission = result.scalar_one_or_none()
    
    if not permission:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="权限不存在"
        )
    
    # 获取权限角色
    query = select(Role).join(RolePermission).where(RolePermission.permission_id == permission_id)
    result = await db.execute(query)
    roles = result.scalars().all()
    
    return {"roles": roles}

@router.get("/resources/list")
@require_permission(PermissionCodes.PERMISSION_READ)
async def get_resource_list(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    # 获取所有资源列表
    result = await db.execute(select(Permission.resource).distinct())
    resources = result.scalars().all()
    
    return {"resources": list(set(resources))}

@router.get("/actions/list")
@require_permission(PermissionCodes.PERMISSION_READ)
async def get_action_list(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    # 获取所有操作列表
    result = await db.execute(select(Permission.action).distinct())
    actions = result.scalars().all()
    
    return {"actions": list(set(actions))}
